/** @file
 *****************************************************************************
 * @author     This file is part of libff, developed by SCIPR Lab
 *             and contributors (see AUTHORS).
 * @copyright  MIT license (see LICENSE file)
 *****************************************************************************/

#include <libff/algebra/curves/alt_bn128/alt_bn128_fields.hpp>

namespace libff {

bigint<alt_bn128_r_limbs> alt_bn128_modulus_r;
bigint<alt_bn128_q_limbs> alt_bn128_modulus_q;

void init_alt_bn128_fields()
{
    using bigint_r = bigint<alt_bn128_r_limbs>;
    using bigint_q = bigint<alt_bn128_q_limbs>;

    assert(sizeof(mp_limb_t) == 8 || sizeof(mp_limb_t) == 4); // Montgomery assumes this

    /* parameters for scalar field Fr */

    alt_bn128_modulus_r = bigint_r("21888242871839275222246405745257275088548364400416034343698204186575808495617");
    assert(alt_bn128_Fr::modulus_is_valid());
    if (sizeof(mp_limb_t) == 8)
    {
        alt_bn128_Fr::Rsquared = bigint_r("944936681149208446651664254269745548490766851729442924617792859073125903783");
        alt_bn128_Fr::Rcubed = bigint_r("5866548545943845227489894872040244720403868105578784105281690076696998248512");
        alt_bn128_Fr::inv = 0xc2e1f593efffffff;
    }
    if (sizeof(mp_limb_t) == 4)
    {
        alt_bn128_Fr::Rsquared = bigint_r("944936681149208446651664254269745548490766851729442924617792859073125903783");
        alt_bn128_Fr::Rcubed = bigint_r("5866548545943845227489894872040244720403868105578784105281690076696998248512");
        alt_bn128_Fr::inv = 0xefffffff;
    }
    alt_bn128_Fr::num_bits = 254;
    alt_bn128_Fr::euler = bigint_r("10944121435919637611123202872628637544274182200208017171849102093287904247808");
    alt_bn128_Fr::s = 28;
    alt_bn128_Fr::t = bigint_r("81540058820840996586704275553141814055101440848469862132140264610111");
    alt_bn128_Fr::t_minus_1_over_2 = bigint_r("40770029410420498293352137776570907027550720424234931066070132305055");
    alt_bn128_Fr::multiplicative_generator = alt_bn128_Fr("5");
    alt_bn128_Fr::root_of_unity = alt_bn128_Fr("19103219067921713944291392827692070036145651957329286315305642004821462161904");
    alt_bn128_Fr::nqr = alt_bn128_Fr("5");
    alt_bn128_Fr::nqr_to_t = alt_bn128_Fr("19103219067921713944291392827692070036145651957329286315305642004821462161904");

    /* parameters for base field Fq */

    alt_bn128_modulus_q = bigint_q("21888242871839275222246405745257275088696311157297823662689037894645226208583");
    assert(alt_bn128_Fq::modulus_is_valid());
    if (sizeof(mp_limb_t) == 8)
    {
        alt_bn128_Fq::Rsquared = bigint_q("3096616502983703923843567936837374451735540968419076528771170197431451843209");
        alt_bn128_Fq::Rcubed = bigint_q("14921786541159648185948152738563080959093619838510245177710943249661917737183");
        alt_bn128_Fq::inv = 0x87d20782e4866389;
    }
    if (sizeof(mp_limb_t) == 4)
    {
        alt_bn128_Fq::Rsquared = bigint_q("3096616502983703923843567936837374451735540968419076528771170197431451843209");
        alt_bn128_Fq::Rcubed = bigint_q("14921786541159648185948152738563080959093619838510245177710943249661917737183");
        alt_bn128_Fq::inv = 0xe4866389;
    }
    alt_bn128_Fq::num_bits = 254;
    alt_bn128_Fq::euler = bigint_q("10944121435919637611123202872628637544348155578648911831344518947322613104291");
    alt_bn128_Fq::s = 1;
    alt_bn128_Fq::t = bigint_q("10944121435919637611123202872628637544348155578648911831344518947322613104291");
    alt_bn128_Fq::t_minus_1_over_2 = bigint_q("5472060717959818805561601436314318772174077789324455915672259473661306552145");
    alt_bn128_Fq::multiplicative_generator = alt_bn128_Fq("3");
    alt_bn128_Fq::root_of_unity = alt_bn128_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582");
    alt_bn128_Fq::nqr = alt_bn128_Fq("3");
    alt_bn128_Fq::nqr_to_t = alt_bn128_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582");

    /* parameters for twist field Fq2 */

    alt_bn128_Fq2::euler = bigint<2*alt_bn128_q_limbs>("239547588008311421220994022608339370399626158265550411218223901127035046843189118723920525909718935985594116157406550130918127817069793474323196511433944");
    alt_bn128_Fq2::s = 4;
    alt_bn128_Fq2::t = bigint<2*alt_bn128_q_limbs>("29943448501038927652624252826042421299953269783193801402277987640879380855398639840490065738714866998199264519675818766364765977133724184290399563929243");
    alt_bn128_Fq2::t_minus_1_over_2 = bigint<2*alt_bn128_q_limbs>("14971724250519463826312126413021210649976634891596900701138993820439690427699319920245032869357433499099632259837909383182382988566862092145199781964621");
    alt_bn128_Fq2::non_residue = alt_bn128_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582");
    alt_bn128_Fq2::nqr = alt_bn128_Fq2(alt_bn128_Fq("2"),alt_bn128_Fq("1"));
    alt_bn128_Fq2::nqr_to_t = alt_bn128_Fq2(alt_bn128_Fq("5033503716262624267312492558379982687175200734934877598599011485707452665730"),alt_bn128_Fq("314498342015008975724433667930697407966947188435857772134235984660852259084"));
    alt_bn128_Fq2::Frobenius_coeffs_c1[0] = alt_bn128_Fq("1");
    alt_bn128_Fq2::Frobenius_coeffs_c1[1] = alt_bn128_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582");

    /* parameters for Fq6 */

    alt_bn128_Fq6::euler = bigint<6*alt_bn128_q_limbs>("5498388192958968685942133058043672206732751847567792101833005999610030333730837412886721209788291211298383180141055457431344429976884849349913268061994433794710968384709566373503289284049367666702094574752748221137683704401917587"
                                                       "7068998572693741735838873805855113185414083578466773124823719245338616604713715536237007459144818392105176489621967934260959676496778033242067460465148059540293548160766892478385479634355306233598756643954842572490928255038258184");
    alt_bn128_Fq6::s = 4;
    alt_bn128_Fq6::t = bigint<6*alt_bn128_q_limbs>("6872985241198710857427666322554590258415939809459740127291257499512537917163546766108401512235364014122978975176319321789180537471106061687391585077493042243388710480886957966879111605061709583377618218440935276422104630502396984"
                                                   "633624821586717716979859225731889148176760447308346640602964905667327075589214442029625932393102299013147061202745991782619959562097254155258432558143507442536693520095861559798184954294413279199844580494355321561366031879782273");
    alt_bn128_Fq6::t_minus_1_over_2 = bigint<6*alt_bn128_q_limbs>("3436492620599355428713833161277295129207969904729870063645628749756268958581773383054200756117682007061489487588159660894590268735553030843695792538746521121694355240443478983439555802530854791688809109220467638211052315251198492"
                                                                  "316812410793358858489929612865944574088380223654173320301482452833663537794607221014812966196551149506573530601372995891309979781048627077629216279071753721268346760047930779899092477147206639599922290247177660780683015939891136");
    alt_bn128_Fq6::non_residue = alt_bn128_Fq2(alt_bn128_Fq("9"),alt_bn128_Fq("1"));
    alt_bn128_Fq6::nqr = alt_bn128_Fq6(alt_bn128_Fq2::one(),alt_bn128_Fq2::one(),alt_bn128_Fq2::zero());
    alt_bn128_Fq6::nqr_to_t = alt_bn128_Fq6(alt_bn128_Fq2(alt_bn128_Fq("5033503716262624267312492558379982687175200734934877598599011485707452665730"),alt_bn128_Fq("314498342015008975724433667930697407966947188435857772134235984660852259084")),
                                            alt_bn128_Fq2::zero(),alt_bn128_Fq2::zero());
    alt_bn128_Fq6::Frobenius_coeffs_c1[0] = alt_bn128_Fq2(alt_bn128_Fq("1"),alt_bn128_Fq("0"));
    alt_bn128_Fq6::Frobenius_coeffs_c1[1] = alt_bn128_Fq2(alt_bn128_Fq("21575463638280843010398324269430826099269044274347216827212613867836435027261"),alt_bn128_Fq("10307601595873709700152284273816112264069230130616436755625194854815875713954"));
    alt_bn128_Fq6::Frobenius_coeffs_c1[2] = alt_bn128_Fq2(alt_bn128_Fq("21888242871839275220042445260109153167277707414472061641714758635765020556616"),alt_bn128_Fq("0"));
    alt_bn128_Fq6::Frobenius_coeffs_c1[3] = alt_bn128_Fq2(alt_bn128_Fq("3772000881919853776433695186713858239009073593817195771773381919316419345261"),alt_bn128_Fq("2236595495967245188281701248203181795121068902605861227855261137820944008926"));
    alt_bn128_Fq6::Frobenius_coeffs_c1[4] = alt_bn128_Fq2(alt_bn128_Fq("2203960485148121921418603742825762020974279258880205651966"),alt_bn128_Fq("0"));
    alt_bn128_Fq6::Frobenius_coeffs_c1[5] = alt_bn128_Fq2(alt_bn128_Fq("18429021223477853657660792034369865839114504446431234726392080002137598044644"),alt_bn128_Fq("9344045779998320333812420223237981029506012124075525679208581902008406485703"));
    alt_bn128_Fq6::Frobenius_coeffs_c2[0] = alt_bn128_Fq2(alt_bn128_Fq("1"),alt_bn128_Fq("0"));
    alt_bn128_Fq6::Frobenius_coeffs_c2[1] = alt_bn128_Fq2(alt_bn128_Fq("2581911344467009335267311115468803099551665605076196740867805258568234346338"),alt_bn128_Fq("19937756971775647987995932169929341994314640652964949448313374472400716661030"));
    alt_bn128_Fq6::Frobenius_coeffs_c2[2] = alt_bn128_Fq2(alt_bn128_Fq("2203960485148121921418603742825762020974279258880205651966"),alt_bn128_Fq("0"));
    alt_bn128_Fq6::Frobenius_coeffs_c2[3] = alt_bn128_Fq2(alt_bn128_Fq("5324479202449903542726783395506214481928257762400643279780343368557297135718"),alt_bn128_Fq("16208900380737693084919495127334387981393726419856888799917914180988844123039"));
    alt_bn128_Fq6::Frobenius_coeffs_c2[4] = alt_bn128_Fq2(alt_bn128_Fq("21888242871839275220042445260109153167277707414472061641714758635765020556616"),alt_bn128_Fq("0"));
    alt_bn128_Fq6::Frobenius_coeffs_c2[5] = alt_bn128_Fq2(alt_bn128_Fq("13981852324922362344252311234282257507216387789820983642040889267519694726527"),alt_bn128_Fq("7629828391165209371577384193250820201684255241773809077146787135900891633097"));

    /* parameters for Fq12 */

    alt_bn128_Fq12::euler = bigint<12*alt_bn128_q_limbs>("6046454544094118612696716508779587437811568806609539163841022840837511675160439295069809579470726816362285317189074189593010054711753278639030702124756988051901885569977000289997599951414317131996165287196109395898133161740013239"
                                                         "9888297521435321796045181656948751979423639329028967870230773431739673019331878848229304257798356000945534097884727669953970987792240845774002479163950538365882113983376282498734078978127251495373970720242630990733199570106949023"
                                                         "7762076416585403922810013029850683334917030622308132823590417497097051812125040060283944081016629563604381750765903889723685281433578635694885707011225313483583616375087345107775624111047238927818711997768928884593065817839459018"
                                                         "6562743353071320465908984361117040009944460908570918928026578161925375182627523989293890456243197793702483966432294320134848198228187915704499812007832429165557659647468827260733943113908864341788809250341940281027139567362472080");
    alt_bn128_Fq12::s = 5;
    alt_bn128_Fq12::t = bigint<12*alt_bn128_q_limbs>("3779034090058824132935447817987242148632230504130961977400639275523444796975274559418630987169204260226428323243171368495631284194845799149394188827973117532438678481235625181248499969633948207497603304497568372436333226087508274"
                                                     "9930185950897076122528238535592969987139774580643104918894233394837295637082424280143315161123972500590958811177954793721231867370150528608751549477469086478676321239610176561708799361329532184608731700151644369208249731316843139"
                                                     "8601297760365877451756258143656677084323144138942583014744010935685657382578150037677465050635393477252738594228689931077303300895986647309303566882015820927239760234429590692359765069404524329886694998605580552870666136149661886"
                                                     "660171459566957529119311522569815000621528806785682433001661135120335948914220249330868153515199862106405247902018395008428012389261744731531238250489526822847353727966801703795871444619304021361800578146371267564196222960154505");
    alt_bn128_Fq12::t_minus_1_over_2 = bigint<12*alt_bn128_q_limbs>("1889517045029412066467723908993621074316115252065480988700319637761722398487637279709315493584602130113214161621585684247815642097422899574697094413986558766219339240617812590624249984816974103748801652248784186218166613043754137"
                                                                    "4965092975448538061264119267796484993569887290321552459447116697418647818541212140071657580561986250295479405588977396860615933685075264304375774738734543239338160619805088280854399680664766092304365850075822184604124865658421569"
                                                                    "9300648880182938725878129071828338542161572069471291507372005467842828691289075018838732525317696738626369297114344965538651650447993323654651783441007910463619880117214795346179882534702262164943347499302790276435333068074830943"
                                                                    "330085729783478764559655761284907500310764403392841216500830567560167974457110124665434076757599931053202623951009197504214006194630872365765619125244763411423676863983400851897935722309652010680900289073185633782098111480077252");
    alt_bn128_Fq12::non_residue = alt_bn128_Fq2(alt_bn128_Fq("9"),alt_bn128_Fq("1"));
    alt_bn128_Fq12::nqr = alt_bn128_Fq12(alt_bn128_Fq6::one(), alt_bn128_Fq6::one());
    alt_bn128_Fq12::nqr_to_t = alt_bn128_Fq12(alt_bn128_Fq6::zero(),
                                              alt_bn128_Fq6(alt_bn128_Fq2::zero(),alt_bn128_Fq2(alt_bn128_Fq("7299059822208274084482252430043382812017501266368539931062816119060212104055"),alt_bn128_Fq("9394737973577957017988251966646482882049672572091998406660728871491334118516")),alt_bn128_Fq2::zero()));
    alt_bn128_Fq12::Frobenius_coeffs_c1[0]  = alt_bn128_Fq2(alt_bn128_Fq("1"),alt_bn128_Fq("0"));
    alt_bn128_Fq12::Frobenius_coeffs_c1[1]  = alt_bn128_Fq2(alt_bn128_Fq("8376118865763821496583973867626364092589906065868298776909617916018768340080"),alt_bn128_Fq("16469823323077808223889137241176536799009286646108169935659301613961712198316"));
    alt_bn128_Fq12::Frobenius_coeffs_c1[2]  = alt_bn128_Fq2(alt_bn128_Fq("21888242871839275220042445260109153167277707414472061641714758635765020556617"),alt_bn128_Fq("0"));
    alt_bn128_Fq12::Frobenius_coeffs_c1[3]  = alt_bn128_Fq2(alt_bn128_Fq("11697423496358154304825782922584725312912383441159505038794027105778954184319"),alt_bn128_Fq("303847389135065887422783454877609941456349188919719272345083954437860409601"));
    alt_bn128_Fq12::Frobenius_coeffs_c1[4]  = alt_bn128_Fq2(alt_bn128_Fq("21888242871839275220042445260109153167277707414472061641714758635765020556616"),alt_bn128_Fq("0"));
    alt_bn128_Fq12::Frobenius_coeffs_c1[5]  = alt_bn128_Fq2(alt_bn128_Fq("3321304630594332808241809054958361220322477375291206261884409189760185844239"),alt_bn128_Fq("5722266937896532885780051958958348231143373700109372999374820235121374419868"));
    alt_bn128_Fq12::Frobenius_coeffs_c1[6]  = alt_bn128_Fq2(alt_bn128_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582"),alt_bn128_Fq("0"));
    alt_bn128_Fq12::Frobenius_coeffs_c1[7]  = alt_bn128_Fq2(alt_bn128_Fq("13512124006075453725662431877630910996106405091429524885779419978626457868503"),alt_bn128_Fq("5418419548761466998357268504080738289687024511189653727029736280683514010267"));
    alt_bn128_Fq12::Frobenius_coeffs_c1[8]  = alt_bn128_Fq2(alt_bn128_Fq("2203960485148121921418603742825762020974279258880205651966"),alt_bn128_Fq("0"));
    alt_bn128_Fq12::Frobenius_coeffs_c1[9]  = alt_bn128_Fq2(alt_bn128_Fq("10190819375481120917420622822672549775783927716138318623895010788866272024264"),alt_bn128_Fq("21584395482704209334823622290379665147239961968378104390343953940207365798982"));
    alt_bn128_Fq12::Frobenius_coeffs_c1[10] = alt_bn128_Fq2(alt_bn128_Fq("2203960485148121921418603742825762020974279258880205651967"),alt_bn128_Fq("0"));
    alt_bn128_Fq12::Frobenius_coeffs_c1[11] = alt_bn128_Fq2(alt_bn128_Fq("18566938241244942414004596690298913868373833782006617400804628704885040364344"),alt_bn128_Fq("16165975933942742336466353786298926857552937457188450663314217659523851788715"));
}

} // namespace libff
